package gdma.hqdes.article.policy;

import com.deepoove.poi.data.style.ParagraphStyle;
import com.deepoove.poi.data.style.Style;
import com.deepoove.poi.policy.DynamicTableRenderPolicy;
import com.deepoove.poi.util.StyleUtils;
import com.deepoove.poi.util.TableTools;
import common.util.ListUtils;
import gdma.hqdes.bean.HqdIndex;
import lombok.NoArgsConstructor;
import org.apache.poi.xwpf.usermodel.*;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTcPr;
import org.springframework.util.CollectionUtils;

import java.util.List;

/**
 * @Author wangyue
 * @Version 3.0
 * @Date 2024-07-26
 */
@NoArgsConstructor
public class UnitScoreTablePolicy extends DynamicTableRenderPolicy {

    int maxLevel = 3;

    private XWPFTableRow sampleRow;

    public UnitScoreTablePolicy(int maxLevel) {
        this.maxLevel = maxLevel;
    }

    @Override
    public void render(XWPFTable table, Object data) throws Exception {
        if(null == data) return;
        sampleRow = table.getRow(1);
        renderRows((List<HqdIndex>)data, table, 1, 0);
    }

    private int renderRows(List<HqdIndex> indexScores, XWPFTable table, int startRow, int startCol) {
        int endRow = startRow;
        for(HqdIndex indexScore : indexScores) {
            startRow = endRow;
            XWPFTableRow row = getOrClone(table, startRow);
            XWPFTableCell indexCell = row.getCell(startCol);
            updateText(indexCell, "(" + indexScore.getCode() + ")" + indexScore.getName());
            XWPFTableCell scoreCell = row.getCell(startCol + 1);
            updateText(scoreCell, String.valueOf(indexScore.getUnitScore() != null ? indexScore.getUnitScore().getScore() : 0f));
            endRow = !CollectionUtils.isEmpty(indexScore.getChildren()) && indexScore.getLevel() < maxLevel ?
                    renderRows(indexScore.getChildren(), table, startRow, startCol + 2) :
                    startRow + 1;
            if(endRow - startRow > 1) {
                TableTools.mergeCellsVertically(table, startCol, startRow, endRow - 1);
                TableTools.mergeCellsVertically(table, startCol + 1, startRow, endRow - 1);
            }
        }
        return endRow;
    }

    private XWPFTableRow  getOrClone(XWPFTable table, int pos) {
        XWPFTableRow row = table.getRow(pos);
        if(row == null) {
            row = cloneRow(sampleRow, table, pos);
        }
        return row;
    }

    private static XWPFTableRow cloneRow(XWPFTableRow sourceRow, XWPFTable table, int pos) {
        XWPFTableRow targetRow = table.insertNewTableRow(pos);

        List<XWPFTableCell> sourceCells = sourceRow.getTableCells();
        for (XWPFTableCell sourceCell : sourceCells) {
            XWPFTableCell newCell = targetRow.addNewTableCell();
            CTTcPr sourceTcPr = sourceCell.getCTTc().getTcPr();
            CTTcPr targetTcPr = newCell.getCTTc().addNewTcPr();
            copyCTTcPrWithoutMergeInfo(sourceTcPr, targetTcPr);

            //其实无论是哪里来的XWPFTableCell直接取0索引都是安全的
            XWPFParagraph sourceParagraph = ListUtils.getOrNull(sourceCell.getParagraphs(), 0);
            if(sourceParagraph != null) {
                XWPFParagraph paragraph = ListUtils.getOrNull(newCell.getParagraphs(),0);
                if(paragraph == null) paragraph = newCell.addParagraph();
                ParagraphStyle paragraphStyle = StyleUtils.retriveParagraphStyle(sourceParagraph);
                if(paragraphStyle != null) StyleUtils.styleParagraph(paragraph, paragraphStyle);

                //XWPFParagraph取0索引经常不安全，必须判空
                XWPFRun sourceRun = ListUtils.getOrNull(sourceParagraph.getRuns(), 0);
                if(sourceRun != null) {
                    XWPFRun run = ListUtils.getOrNull(paragraph.getRuns(), 0);
                    if(run == null) run = paragraph.createRun();
                    Style runStyle = StyleUtils.retriveStyle(sourceRun);
                    if(runStyle != null) StyleUtils.styleRun(run, runStyle);
                }
            }
        }

        return targetRow;
    }

    public static void copyCTTcPrWithoutMergeInfo(CTTcPr source, CTTcPr target) {
        if (source == null || target == null) {
            return;
        }
        if (source.isSetTcW()) {
            target.setTcW(source.getTcW());
        }
        if (source.isSetShd()) {
            target.setShd(source.getShd());
        }
        if (source.isSetVAlign()) {
            target.setVAlign(source.getVAlign());
        }
        if (source.isSetTextDirection()) {
            target.setTextDirection(source.getTextDirection());
        }
        if (source.isSetNoWrap()) {
            target.setNoWrap(source.getNoWrap());
        }
        if (source.isSetTcBorders()) {
            target.setTcBorders(source.getTcBorders());
        }
        if (source.isSetTcMar()) {
            target.setTcMar(source.getTcMar());
        }
        if (source.isSetTcFitText()) {
            target.setTcFitText(source.getTcFitText());
        }
        if (source.isSetGridSpan()) {
            target.setGridSpan(source.getGridSpan());
        }
        if (source.isSetHideMark()) {
            target.setHideMark(source.getHideMark());
        }
        if (source.isSetCnfStyle()) {
            target.setCnfStyle(source.getCnfStyle());
        }
    }

    public static void updateText(XWPFTableCell cell, String newText) {
        XWPFParagraph paragraph = ListUtils.getOrNull(cell.getParagraphs(), 0);
        if(paragraph != null) {
            XWPFRun run = ListUtils.getOrNull(paragraph.getRuns(), 0);
            if(run != null) {
                run.setText(newText, 0);
                return;
            }
        }
        cell.setText(newText);
    }

}
